package proxy

import (
	"crypto/tls"
	"fmt"

	"gitee.com/xuender/mysql-proxy/pb"
	"github.com/go-ldap/ldap"
	"github.com/xuender/oils/logs"
)

type LdapService struct {
	c *pb.Config
}

func NewLdapService(config *pb.Config) *LdapService {
	return &LdapService{c: config}
}

func (p *LdapService) Bind(user, password string) (isOK bool, err error) {
	var ldapConn *ldap.Conn

	if p.c.Ldap.Ldaps {
		// nolint
		ldapConn, err = ldap.DialTLS("tcp", p.c.Ldap.Url, &tls.Config{InsecureSkipVerify: true})
	} else {
		ldapConn, err = ldap.Dial("tcp", p.c.Ldap.Url)
	}

	if err != nil {
		return
	}

	defer ldapConn.Close()

	if ldapConn != nil {
		if err = ldapConn.Bind(p.c.Ldap.User, p.c.Ldap.Password); err != nil {
			return
		}
	}

	searchRequest := ldap.NewSearchRequest(
		p.c.Ldap.Sc,
		ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
		fmt.Sprintf(p.c.Ldap.Filter, user),
		[]string{"dn"},
		nil,
	)

	search, err := ldapConn.Search(searchRequest)
	if err != nil {
		return false, err
	}

	if len(search.Entries) != 1 {
		return false, ErrLdapUser
	}

	userdn := search.Entries[0].DN

	logs.Debugw("dn", "dn", userdn)

	if err := ldapConn.Bind(userdn, password); err != nil {
		return false, err
	}

	return true, nil
}
